package com.linoer.cloud.alo.businessserver.service.imp;

import com.linoer.cloud.alo.businessserver.service.BusinessService;
import com.linoer.cloud.alo.common.domain.dto.AccountDTO;
import com.linoer.cloud.alo.common.domain.ObjectResponse;
import com.linoer.cloud.alo.common.domain.dto.BusinessDTO;
import com.linoer.cloud.alo.common.domain.dto.OrderDTO;
import com.linoer.cloud.alo.common.domain.dto.StorageDTO;
import com.linoer.cloud.alo.common.service.dubbo.AccountDubboService;
import com.linoer.cloud.alo.common.service.dubbo.OrderDubboService;
import com.linoer.cloud.alo.common.service.dubbo.StorageDubboService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @Classname BusinessServiceImp
 * @Description TODO
 * @Date 2021/6/22 4:34 下午
 * @Created by muhenglv
 */
@Slf4j
@Service
public class BusinessServiceImp implements BusinessService {
    @Reference(version = "1.0.0", protocol = "dubbo", timeout = 5000)
    private StorageDubboService storageDubboService;
    @Reference(version = "1.0.0", protocol = "dubbo", timeout = 5000)
    private AccountDubboService accountDubboService;
    @Reference(version = "1.0.0", protocol = "dubbo", timeout = 5000)
    private OrderDubboService orderDubboService;

    private boolean flag = false;

    @GlobalTransactional(timeoutMills = 300000, name = "dubbo-gts-seata-example")
    @Override
    public ObjectResponse purchase(BusinessDTO businessDTO) {
        log.info("purchase开始全局事务，XID = " + RootContext.getXID());
        // 扣除账户金额
        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setUserId(businessDTO.getUserId());
        accountDTO.setMoney(businessDTO.getAmount());
        ObjectResponse accountResponse = accountDubboService.decreaseAccount(accountDTO);
        log.info("[accountResponse|{}]", accountResponse);

        // 减小库存
        StorageDTO storageDTO = new StorageDTO();
        storageDTO.setCommodityCode(businessDTO.getCommodityId());
        storageDTO.setCount(businessDTO.getCount());
        ObjectResponse storageResponse = storageDubboService.decreaseStorage(storageDTO);
        log.info("[storageResponse|{}]", storageResponse);

        // 生成订单
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setCommodityCode(businessDTO.getCommodityId());
        orderDTO.setCount(businessDTO.getCount());
        orderDTO.setOrderId(UUID.randomUUID() + "");
        orderDTO.setUserId(businessDTO.getUserId());
        orderDTO.setMoney(businessDTO.getAmount());
        ObjectResponse orderResponse = orderDubboService.createOrder(orderDTO);
        log.info("[orderResponse|{}]", orderResponse);

        return orderResponse;
    }

    @Override
    public ObjectResponse purchaseError(BusinessDTO businessDTO) {
        log.info("purchaseError开始全局事务，XID = " + RootContext.getXID());
        // 扣除账户金额
        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setUserId(businessDTO.getUserId());
        accountDTO.setMoney(businessDTO.getAmount());
        ObjectResponse accountResponse = accountDubboService.decreaseAccount(accountDTO);
        log.info("[accountResponse|{}]", accountResponse);

        // 减小库存
        StorageDTO storageDTO = new StorageDTO();
        storageDTO.setCommodityCode(businessDTO.getCommodityId());
        storageDTO.setCount(businessDTO.getCount());
        ObjectResponse storageResponse = storageDubboService.decreaseStorage(storageDTO);
        log.info("[storageResponse|{}]", storageResponse);

        if (!flag) {
            throw new RuntimeException("测试抛异常后，分布式事务回滚！");
        }

        // 生成订单
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setCommodityCode(businessDTO.getCommodityId());
        orderDTO.setCount(businessDTO.getCount());
        orderDTO.setOrderId(UUID.randomUUID() + "");
        orderDTO.setUserId(businessDTO.getUserId());
        orderDTO.setMoney(businessDTO.getAmount());
        ObjectResponse orderResponse = orderDubboService.createOrder(orderDTO);
        log.info("[orderResponse|{}]", orderResponse);

        return null;
    }
}
